﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using FrontEnd.Storage.Layout;
using FrontEnd.Storage;

namespace FrontEnd
{
    public partial class GameListDisplay : UserControl
    {
        #region Member Variables

        private Label m_titleLabel = null;
        private Label m_countLabel = null;

        private GameListStg m_gameList = null;
        private int m_currentIndex = -1;

        private List<Label> m_gameLabels = new List<Label>();
        private int m_selectedGameLabelIndex = -1;

        #endregion

        #region Constructor(s)

        ///-------------------------------------------------------------------------------------------------
        /// <summary> Default constructor. </summary>
        ///-------------------------------------------------------------------------------------------------
        public GameListDisplay()
        {
            InitializeComponent();
        }

        #endregion

        #region Public

        ///-------------------------------------------------------------------------------------------------
        /// <summary> Gets the current game. </summary>
        /// <value> The current game. </value>
        ///-------------------------------------------------------------------------------------------------
        public Game CurrentGame
        {
            get
            {
                // TODO: Need to verify that game lable, index, tag, etc, are valid.
                return (Game)m_gameLabels[m_selectedGameLabelIndex].Tag;
            }
        }

        ///-------------------------------------------------------------------------------------------------
        /// <summary> Loads the settings. </summary>
        /// <exception cref="ArgumentNullException"> Thrown when one or more required arguments are null. </exception>
        /// <param name="settings"> Options for controlling the game list. </param>
        ///-------------------------------------------------------------------------------------------------
        public void LoadSettings(GameListSettings settings)
        {
            if (settings == null)
                throw new ArgumentNullException("settings");

            // Determine row count.
            int rowCount = settings.NumberOfGamesToDisplay;

            if (settings.DisplayTitle)
                rowCount++;

            if (settings.DisplayCount)
                rowCount++;

            // Set column and row counts.
            pnlTableLayout.ColumnCount = 1;
            pnlTableLayout.RowCount = rowCount;

            // Clear row styles.
            pnlTableLayout.RowStyles.Clear();

            // Add title label if applicable.
            if (settings.DisplayTitle)
            {
                pnlTableLayout.RowStyles.Add(new RowStyle(SizeType.Percent, 5));
                m_titleLabel = GenerateLabel(settings.TitleFont, settings.TitleColor);
                pnlTableLayout.Controls.Add(m_titleLabel);
            }
            else
                m_titleLabel = null;

            // Determine size of game sections.
            float gameSectionSize = 100;
            if (settings.DisplayTitle)
                gameSectionSize -= 5;

            if (settings.DisplayCount)
                gameSectionSize -= 5;

            gameSectionSize /= settings.NumberOfGamesToDisplay;

            // Determine number of games before and after selected game.
            int secondSetCount = (settings.NumberOfGamesToDisplay / 2);
            int firstSetCount = (settings.NumberOfGamesToDisplay % 2 == 0) ? secondSetCount - 1 : secondSetCount;

            // Setup game labels.
            for (int i = 0; i < firstSetCount; i++)
            {
                pnlTableLayout.RowStyles.Add(new RowStyle(SizeType.Percent, gameSectionSize));
                m_gameLabels.Add(GenerateLabel(settings.GameFont, settings.GameColor));
                pnlTableLayout.Controls.Add(m_gameLabels[m_gameLabels.Count - 1]);
            }

            pnlTableLayout.RowStyles.Add(new RowStyle(SizeType.Percent, gameSectionSize));
            m_gameLabels.Add(GenerateLabel(settings.SelectedGameFont, settings.SelectedGameColor));
            pnlTableLayout.Controls.Add(m_gameLabels[m_gameLabels.Count - 1]);
            m_selectedGameLabelIndex = m_gameLabels.Count - 1;

            for (int i = 0; i < secondSetCount; i++)
            {
                pnlTableLayout.RowStyles.Add(new RowStyle(SizeType.Percent, gameSectionSize));
                m_gameLabels.Add(GenerateLabel(settings.GameFont, settings.GameColor));
                pnlTableLayout.Controls.Add(m_gameLabels[m_gameLabels.Count - 1]);
            }

            // Add count label if applicable.
            if (settings.DisplayCount)
            {
                pnlTableLayout.RowStyles.Add(new RowStyle(SizeType.Percent, 5));
                m_countLabel = GenerateLabel(settings.CountFont, settings.CountColor);
                pnlTableLayout.Controls.Add(m_countLabel);
            }
            else
                m_countLabel = null;
        }

        ///-------------------------------------------------------------------------------------------------
        /// <summary> Assigns game list. </summary>
        /// <param name="gameList"> List of games. </param>
        ///-------------------------------------------------------------------------------------------------
        public void AssignList(GameListStg gameList)
        {
            if (this.InvokeRequired)
                this.BeginInvoke(new MethodInvoker(delegate { AssignList(gameList); }));
            else if ((gameList == null) || (gameList.Count <= 0))
            {
                m_gameList = null;
                m_currentIndex = -1;

                if (m_titleLabel != null)
                    m_titleLabel.Text = "No List / Empty List";

                if (m_countLabel != null)
                    m_countLabel.Text = "0 / 0";

                foreach (Label gameLabel in m_gameLabels)
                    gameLabel.Text = "";

                m_gameLabels[m_selectedGameLabelIndex].Text = "No Games";
            }
            else
            {
                m_gameList = gameList;
                m_currentIndex = 0;

                if (m_titleLabel != null)
                    m_titleLabel.Text = "List Name";

                if (m_countLabel != null)
                    m_countLabel.Text = String.Format("1 / {0}", gameList.Count);

                UpdateLabels();
            }
        }

        ///-------------------------------------------------------------------------------------------------
        /// <summary> Increments to next game. </summary>
        ///-------------------------------------------------------------------------------------------------
        public void Increment()
        {
            if (this.InvokeRequired)
                this.BeginInvoke(new MethodInvoker(delegate { Increment(); }));
            else if (m_currentIndex < m_gameList.Count - 1)
            {
                m_currentIndex++;

                this.SuspendLayout();

                try
                {
                    UpdateLabels();

                    if (m_countLabel != null)
                        m_countLabel.Text = String.Format("{0} / {1}", (m_currentIndex + 1), m_gameList.Count);
                }
                finally
                {
                    this.ResumeLayout();
                }
            }
        }

        ///-------------------------------------------------------------------------------------------------
        /// <summary> Decrements to previous game. </summary>
        ///-------------------------------------------------------------------------------------------------
        public void Decrement()
        {
            if (this.InvokeRequired)
                this.BeginInvoke(new MethodInvoker(delegate { Decrement(); }));
            else if (m_currentIndex > 0)
            {
                m_currentIndex--;

                this.SuspendLayout();

                try
                {
                    UpdateLabels();

                    if (m_countLabel != null)
                        m_countLabel.Text = String.Format("{0} / {1}", (m_currentIndex + 1), m_gameList.Count);
                }
                finally
                {
                    this.ResumeLayout();
                }
            }
        }

        #endregion

        #region Private Helper Methods

        ///-------------------------------------------------------------------------------------------------
        /// <summary> Updates the labels based on current index. </summary>
        ///-------------------------------------------------------------------------------------------------
        private void UpdateLabels()
        {
            if ((m_currentIndex >= 0) && (m_currentIndex < m_gameList.Count))
            {
                m_gameLabels[m_selectedGameLabelIndex].Text = m_gameList[m_currentIndex].CustomDescription;
                m_gameLabels[m_selectedGameLabelIndex].Tag = m_gameList[m_currentIndex];

                int localIndex = m_currentIndex;
                for (int i = m_selectedGameLabelIndex + 1; i < m_gameLabels.Count; i++)
                {
                    localIndex++;
                    if (localIndex >= m_gameList.Count)
                        m_gameLabels[i].Text = "";
                    else
                        m_gameLabels[i].Text = m_gameList[localIndex].CustomDescription;
                }

                localIndex = m_currentIndex;
                for (int i = m_selectedGameLabelIndex - 1; i >= 0; i--)
                {
                    localIndex--;
                    if (localIndex < 0)
                        m_gameLabels[i].Text = "";
                    else
                        m_gameLabels[i].Text = m_gameList[localIndex].CustomDescription;
                }
            }
        }

        ///-------------------------------------------------------------------------------------------------
        /// <summary> Generates a label. </summary>
        /// <param name="font">  The font. </param>
        /// <param name="color"> The color. </param>
        /// <returns> The label. </returns>
        ///-------------------------------------------------------------------------------------------------
        private Label GenerateLabel(Font font, Color color)
        {
            Label label = new Label();
            label.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
                        | System.Windows.Forms.AnchorStyles.Left)
                        | System.Windows.Forms.AnchorStyles.Right)));
            label.AutoEllipsis = true;
            label.AutoSize = false;
            label.Font = (font == null) ? this.Font : font;
            label.ForeColor = color;
            label.Text = "label";
            label.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
            return label;
        }

        #endregion
    }
}
